/***************************************************
 ** @Desc : This file for 充值
 ** @Time : 2019.04.04 18:01
 ** @Author : Joker
 ** @File : recharge
 ** @Last Modified by : Joker
 ** @Last Modified time: 2019.04.04 18:01
 ** @Software: GoLand
****************************************************/
package controllers

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"recharge/controllers/condition"
	"recharge/models"
	"recharge/sys"
	"recharge/utils"
	"recharge/utils/interface_config"
	"regexp"
	"strconv"
	"strings"
)

type Recharge struct {
	KeepSession
}

var rechargeMdl = models.RechargeRecord{}
var merchantFactor = condition.MerchantFactor{}

// 展示充值页面
// @router /merchant/show_recharge/ [get,post]
func (the *Recharge) ShowRecharge() {
	userName := the.GetSession("userName")
	if userName != nil {
		the.Data["userName"] = userName.(string)
	}
	right := the.GetSession("FilterRight")
	if right != nil {
		the.Data["right"] = right.(int)
	}

	//通道
	//the.Data["channel"] = utils.GetChannelType()

	the.TplName = "recharge.html"
}

// 选择单个通道下所有商户
// @router /merchant/merchant_type/?:params [get]
func (the *Recharge) QueryAllMerchantByType() {
	Type := the.GetString(":params")

	merchants := merchantMdl.SelectAllMerchantByType(Type)

	the.Data["json"] = globalMethod.JsonFormat(utils.SUCCESS_FLAG, merchants, "", "")
	the.ServeJSON()
	the.StopRun()
}

// 商户充值
// @router /merchant/do_recharge/?:params [post]
func (the *Recharge) DoRecharge() {
	userId := the.GetSession("userId").(int)

	//channel := the.GetString("channel")
	//merchant := the.GetString("merchant")
	accountNo := strings.TrimSpace(the.GetString("accountNo"))
	accountName := strings.TrimSpace(the.GetString("accountName"))
	certificateNo := strings.TrimSpace(the.GetString("certificateNo"))
	mobileNo := strings.TrimSpace(the.GetString("mobileNo"))
	recevieBank := the.GetString("recevieBank")
	money := strings.TrimSpace(the.GetString("money"))

	var msg = utils.FAILED_STRING
	var flag = utils.FAILED_FLAG

	matched, _ := regexp.MatchString(`^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$`, money)
	if accountNo == "" || accountName == "" || money == "" {
		msg = "银行卡或户名不能为空!"
	} else if !matched {
		msg = "请输入正确的充值金额哦!"
	} else {
		parseFloat, _ := strconv.ParseFloat(money, 64)
		if parseFloat < utils.SingleMinForRecharge {
			msg = "充值金额单笔不能小于20哦!"
		} else {

			XFMerchant := merchantFactor.QueryOneMerchantForRecharge()

			record := models.RechargeRecord{}
			record.UserId = userId
			record.MerchantNo = XFMerchant.MerchantNo

			record.SerialNumber = utils.XF + globalMethod.GetNowTimeV2() + globalMethod.RandomString(10)
			record.ReOrderId = utils.XF + globalMethod.GetNowTimeV2() + globalMethod.RandomString(8)
			record.ReAmount, _ = globalMethod.MoneyYuanToFloat(money)
			record.ReAccountNo = accountNo
			record.ReAccountName = accountName
			record.ReCertificateType = "0"
			record.ReCertificateNo = certificateNo
			record.ReMobileNo = mobileNo
			record.ReRecevieBank = recevieBank

			record.NoticeUrl = interface_config.XF_RECHANGE_NOTICE_URL + record.ReOrderId

			// 多通道充值
			if strings.Compare(utils.XF, XFMerchant.ChannelType) == 0 {
				//先锋
				record.RecordType = utils.XF

				result, err := xfRecharge(record, XFMerchant.SecretKey)
				if err != nil {
					msg = err.Error()
				} else {

					resp := models.XFRechargeResponseBody{}
					err = json.Unmarshal(result, &resp)
					if err != nil {
						sys.LogError("response data format is error:", err)
						msg = "先锋充值响应数据格式错误"
					} else {

						if strings.Compare("00000", resp.ResCode) != 0 {
							sys.LogDebug("先锋充值错误:", resp)
							msg = "先锋充值错误：" + resp.ResMessage
						} else {

							nowTime := globalMethod.GetNowTime()
							record.CreateTime = nowTime
							record.EditTime = nowTime
							record.Remark = resp.ResMessage

							//状态以异步回调为准
							record.Status = utils.I

							// 添加充值记录
							flag, _ = rechargeMdl.InsertRechargeRecord(record)
						}
					}
				}
			}
		}
	}

	the.Data["json"] = globalMethod.JsonFormat(flag, "", msg, "")
	the.ServeJSON()
	the.StopRun()
}

// 充值手动回调
// @router /merchant/recharge_notice/?:params [get]
func (the *Recharge) RechargeNotice() {
	queryId := the.GetString(":params")

	record := rechargeMdl.SelectOneRechargeRecord(queryId)

	var msg = utils.FAILED_STRING
	var flag = utils.FAILED_FLAG

	if strings.Compare(utils.S, record.Status) == 0 {
		info, _ := userMdl.SelectOneUserById(record.UserId)

		params := models.ApiResponseBody{}
		params.MerchantNo = fmt.Sprintf("%d", record.UserId)
		params.OutTradeNo = record.ReOrderId
		params.TradeStatus = utils.GetApiOrderStatus()[record.Status]
		params.TradeNo = record.SerialNumber
		params.TradeTime = record.EditTime
		params.Item = record.Item

		fee := info.RechargeFee + record.ReAmount*info.RechargeRate*0.001
		params.Amount = globalMethod.MoneyYuanToString(record.ReAmount)
		params.AmountNotFee = globalMethod.MoneyYuanToString(record.ReAmount - fee)
		params.AmountFee = globalMethod.MoneyYuanToString(fee)

		params.ResultCode = "0000"
		params.Msg = record.Remark

		sign := apiRPImpl.GenerateSignV1(params, info.ApiKey)
		params.Sign = sign

		//生成请求参数
		toMap := globalMethod.StructToMap(params)
		byMap := globalMethod.ToStringByMap(toMap)

		//发送请求
		urls := record.ApiNoticeUrl + "?" + byMap
		resp, err := http.Get(urls)
		if err != nil {
			sys.LogError("手动充值异步通知没有响应：", err, record.ApiNoticeUrl)
			msg = "手动充值异步通知没有响应"
		} else {

			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				sys.LogError("手动充值异步通知响应错误：", err)
				msg = "手动充值异步通知响应错误"
			} else if strings.Compare(string(body), "SUCCESS") != 0 {
				msg = "手动充值异步通知没有响应：SUCCESS"
			} else {
				flag = utils.SUCCESS_FLAG
				msg = "手动回调通知成功"
			}
			_ = resp.Body.Close()
		}
	} else {
		msg = "只回调成功的订单！"
	}

	the.Data["json"] = globalMethod.JsonFormat(flag, "", msg, "")
	the.ServeJSON()
	the.StopRun()
}

// 先锋道通充值
func xfRecharge(record models.RechargeRecord, key string) ([]byte, error) {
	// 请求参数
	reqParams := url.Values{}
	reqParams.Add("service", "REQ_OFFLINE_RECHARGE")
	reqParams.Add("secId", interface_config.SECID)
	reqParams.Add("version", interface_config.VERSION)
	reqParams.Add("reqSn", record.SerialNumber)
	reqParams.Add("merchantId", record.MerchantNo)

	// 需要的加密参数
	dataParams := models.XFRechargeData{}
	dataParams.MerchantNo = record.ReOrderId
	fen, _ := globalMethod.MoneyYuanToFen(record.ReAmount)
	dataParams.Amount = fen
	dataParams.TransCur = "156"
	dataParams.AccountNo = record.ReAccountNo
	dataParams.AccountName = record.ReAccountName

	dataParams.RecevieBank = record.ReRecevieBank
	dataParams.NoticeUrl = record.NoticeUrl

	// 加密参数
	dataString, _ := json.Marshal(&dataParams)
	data, err := AES.AesEncrypt(string(dataString), key)
	if err != nil {
		return nil, err
	}

	reqParams.Add("data", data)

	// 生成签名
	respParams := map[string]string{}
	respParams["service"] = "REQ_OFFLINE_RECHARGE"
	respParams["secId"] = interface_config.SECID
	respParams["version"] = interface_config.VERSION
	respParams["reqSn"] = record.SerialNumber
	respParams["merchantId"] = record.MerchantNo
	respParams["data"] = data
	params := globalMethod.ToStringByMap(respParams)

	signBytes, err := merchantImpl.XFGenerateSign(params, key)
	if err != nil {
		s := "先锋充值生成签名失败"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}
	reqParams.Add("sign", string(signBytes))

	// 发送请求
	resp, err := http.PostForm(interface_config.XF_RECHANGE_URL, reqParams)
	if err != nil {
		s := "先锋充值请求失败"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}

	// 处理响应
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		s := "先锋充值响应为空"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}
	defer resp.Body.Close()

	bytes, err := AES.AesDecrypt(body, []byte(key))
	if err != nil {
		s := "先锋充值响应解密错误"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}

	return bytes, err
}
